﻿using Nop.Admin.Models.Common;
using Nop.Admin.Models.XJ;
using Nop.Core;
using Nop.Core.Domain.XJ;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Helpers;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.XJ;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Mvc;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Admin.Controllers
{
	public class InspectionController : BaseAdminController
	{
		#region Fields
		private readonly IPermissionService _permissionService;
		private readonly IPictureService _pictureService;
		private readonly IWorkContext _workContext;
		private readonly IDepartmentService _departmentService;
		private readonly ICustomerService _customerService;
		private readonly IGenericAttributeService _genericAttributeService;
		private readonly IXJPlaceService _xjPlaceService;
		private readonly IXJEquipmentCategoryService _xJEquipmentCategoryService;
		private readonly IXJEquipmentService _xJEquipmentService;
		private readonly IXJEquipmentStockService _xJEquipmentStockService;
		private readonly IXJInspectionService _xJInspectionService;
		private readonly IXJInspectionPlanService _xJInspectionPlanService;
		private readonly IXJMaintenanceService _xJMaintenanceService;
		private readonly IXJMaintenanceCommentService _xJMaintenanceCommentService;
		private readonly ICustomerActivityService _customerActivityService;
		private readonly IDateTimeHelper _dateTimeHelper;
		private readonly ILogger _logger;
		#endregion

		#region Constructors
		public InspectionController(IPermissionService permissionService,
			IPictureService pictureService,
			IWorkContext workContext,
			IDepartmentService departmentService,
			ICustomerService customerService,
			IGenericAttributeService genericAttributeService,
			IXJPlaceService xjPlaceService,
			IXJEquipmentCategoryService xJEquipmentCategoryService,
			IXJEquipmentService xJEquipmentService,
			IXJEquipmentStockService xJEquipmentStockService,
			IXJInspectionService xJInspectionService,
			IXJInspectionPlanService xJInspectionPlanService,
			IXJMaintenanceService xJMaintenanceService,
			IXJMaintenanceCommentService xJMaintenanceCommentService,
			ICustomerActivityService customerActivityService,
			IDateTimeHelper dateTimeHelper,
			ILogger logger)
		{
			this._permissionService = permissionService;
			this._pictureService = pictureService;
			this._workContext = workContext;
			this._departmentService = departmentService;
			this._customerService = customerService;
			this._genericAttributeService = genericAttributeService;
			this._xjPlaceService = xjPlaceService;
			this._xJEquipmentCategoryService = xJEquipmentCategoryService;
			this._xJEquipmentService = xJEquipmentService;
			this._xJEquipmentStockService = xJEquipmentStockService;
			this._xJInspectionService = xJInspectionService;
			this._xJInspectionPlanService = xJInspectionPlanService;
			this._xJMaintenanceService = xJMaintenanceService;
			this._xJMaintenanceCommentService = xJMaintenanceCommentService;
			this._customerActivityService = customerActivityService;
			this._dateTimeHelper = dateTimeHelper;
			this._logger = logger;
		}
		#endregion

		#region Utilities

		[NonAction]
		protected virtual void PrepareAllTypesModel(InspectionModel model)
		{
			if (model == null)
				throw new ArgumentNullException("model");

			Type enumInspectionType = typeof(InspectionTypeEnum);
			Enum.GetNames(enumInspectionType).ToList().ForEach(s =>
			{
				string value = Enum.Format(enumInspectionType, Enum.Parse(enumInspectionType, s), "d");
				model.AvailableTypes.Add(new SelectListItem { Text = s, Value = value });
			});
			model.AvailableDepartments.Add(new SelectMenuModel
			{
				name = "请选择",
				id = 0,
				open = true,
			});
			var departments = _departmentService.GetAllDepartments(showHidden: false);
			foreach (var c in departments)
				model.AvailableDepartments.Add(new SelectMenuModel { name = c.Name, id = c.Id, pId = c.PId });
			model.AvailableUsers.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			if (model.TeamId > 0)
			{
				var users = _customerService.GetAllCustomers(
					//customerRoleIds: new[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered).Id },
					departId: model.TeamId).ToList();
				if (users.Any())
				{
					foreach (var u in users)
					{
						model.AvailableUsers.Add(new SelectListItem
						{
							Text = u.TrueName ?? u.Username,
							Value = u.Id.ToString(),
							Selected = model.TeamId == u.Id
						});
					}
				}
			}
		}

		#endregion

		#region List
		public ActionResult Index()
		{
			return RedirectToAction("List");
		}

		public virtual ActionResult List()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedView();

			var model = new InspectionListModel();

			model.AvailableTypes.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			Type enumInspectionType = typeof(InspectionTypeEnum);
			Enum.GetNames(enumInspectionType).ToList().ForEach(s =>
			{
				string value = Enum.Format(enumInspectionType, Enum.Parse(enumInspectionType, s), "d");
				model.AvailableTypes.Add(new SelectListItem { Text = s, Value = value });
			});
			//model.AvailableCategorys.Add(new SelectMenuModel
			//{
			//	name = "全部",
			//	id = 0,
			//	open = true,
			//});
			//var categorys = _xJEquipmentCategoryService.GetAllCategorys(isConsumables: false, showHidden: false);
			//foreach (var c in categorys)
			//	model.AvailableCategorys.Add(new SelectMenuModel { name = c.Name, id = c.Id, pId = c.PId });

			model.AvailableCategorys.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var categorys = _xJEquipmentCategoryService.GetAllXJEquipmentCategorys().Where(m => m.PId == 0 && !m.IsConsumables);
			foreach (var c in categorys)
				model.AvailableCategorys.Add(new SelectListItem { Text = c.Name, Value = c.Id.ToString() });
			model.AvailablePlaces.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var places = _xjPlaceService.GetAllPlaces(showHidden: false);
			foreach (var p in places)
				model.AvailablePlaces.Add(new SelectListItem { Text = p.Name, Value = p.Id.ToString() });
			model.AvailableDepartments.Add(new SelectMenuModel
			{
				name = "全部",
				id = 0,
				open = true,
			});
			var departments = _departmentService.GetAllDepartments(showHidden: false);
			foreach (var d in departments)
				model.AvailableDepartments.Add(new SelectMenuModel { name = d.Name, id = d.Id, pId = d.PId });
			model.AvailableUsers.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var users = _customerService.GetAllCustomers().Select(x => new { id = x.Id, name = x.TrueName ?? x.Username }).ToList();
			foreach (var item in users)
				model.AvailableUsers.Add(new SelectListItem { Text = item.name, Value = item.id.ToString() });
			return View(model);
		}

		[HttpPost]
		public virtual ActionResult List(DataSourceRequest command, InspectionListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedKendoGridJson();

			if (_permissionService.Authorize(StandardPermissionProvider.ManageInspectionsAll))
			{
				var categories = _xJInspectionService.GetAllInspections(
					typeId: model.SearchTypeId,
					departId: model.SearchDepartId,
					aimId: model.SearchAimId,
					categoryId: model.SearchCategoryId,
					placeId: model.SearchPlaceId,
					teamId: model.SearchTeamId,
					personId: model.SearchPersonId,
					planId: model.SearchPlanId,
					no: model.SearchPNo,
					name: model.SearchName,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var gridModel = new DataSourceResult
				{
					Data = categories.Select(x =>
					{
						if (string.IsNullOrEmpty(x.Name))
						{
							switch (x.AimId)
							{
								case (int)AimTypeEnum.设备分类:
									x.Name = string.Join(",", x.Categorys.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
									break;
								case (int)AimTypeEnum.巡检点:
									x.Name = string.Join(",", x.Places.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
									break;
								default:
									break;
							}
						}
						x.TypeName = Enum.GetName(typeof(InspectionTypeEnum), x.TypeId);
						return x;
					}),
					Total = categories.TotalCount
				};
				return Json(gridModel);
			}
			else
			{
				var customer = _workContext.CurrentCustomer;

				var categories = _xJInspectionService.GetMyInspections(
					customer: customer,
					typeId: model.SearchTypeId,
					departId: model.SearchDepartId,
					aimId: model.SearchAimId,
					categoryId: model.SearchCategoryId,
					placeId: model.SearchPlaceId,
					planId: model.SearchPlanId,
					no: model.SearchPNo,
					name: model.SearchName,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var gridModel = new DataSourceResult
				{
					Data = categories.Select(x =>
					{
						if (string.IsNullOrEmpty(x.Name))
						{
							switch (x.AimId)
							{
								case (int)AimTypeEnum.设备分类:
									x.Name = string.Join(",", x.Categorys.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
									break;
								case (int)AimTypeEnum.巡检点:
									x.Name = string.Join(",", x.Places.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
									break;
								default:
									break;
							}
						}
						x.TypeName = Enum.GetName(typeof(InspectionTypeEnum), x.TypeId);
						return x;
					}),
					Total = categories.TotalCount
				};
				return Json(gridModel);
			}
		}
		#endregion

		#region Edit / Delete

		public virtual ActionResult View(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedView();

			var inspection = _xJInspectionService.GetXJInspectionById(id);
			if (inspection == null)
				//No equipment found with the specified id
				return RedirectToAction("List");

			var model = new InspectionModel
			{
				Id = inspection.Id,
				InspectionPlanId = inspection.InspectionPlanId,
				Comment = inspection.Comment,
				CustomerId = inspection.CustomerId,
				CustomerName = inspection.CustomerName,
				CreatedOn = inspection.CreatedOn,
			};

			var plan = _xJInspectionPlanService.GetXJInspectionPlanById(inspection.InspectionPlanId);
			if (null != plan)
			{
				model.PNo = plan.PNo;
				model.Name = plan.Name;
				model.TypeId = plan.TypeId;
				model.TypeName = Enum.GetName(typeof(InspectionTypeEnum), plan.TypeId);
				model.AimId = plan.AimId;
				model.AimName = Enum.GetName(typeof(AimTypeEnum), plan.AimId);
				model.TeamId = plan.TeamId;
				model.PersonId = plan.PersonId;
				if (plan.TeamId > 0)
				{
					model.TeamName = _departmentService.GetNameById(plan.TeamId);
				}
				//if (plan.PersonId > 0)
				//{
				//	model.PersonName = _customerService.GetNameById(plan.PersonId);
				//}
				switch (plan.AimId)
				{
					case (int)AimTypeEnum.设备分类:
						model.Content = string.Join(",", plan.Categorys.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
						break;
					case (int)AimTypeEnum.巡检点:
						model.Content = string.Join(",", plan.Places.Where(m => !m.Deleted && m.Published).Select(d => d.Name).ToArray());
						break;
					default:
						break;
				}
			}

			var maintenance = _xJMaintenanceService.GetXJMaintenanceByInspectionId(inspection.Id);
			if (null != maintenance)
			{
				model.MaintenanceId = maintenance.Id;
				model.XNo = maintenance.SNo;
			}

			var pictures = inspection.GetAttribute<string>("Pictures");
			if (!string.IsNullOrEmpty(pictures))
			{
				var pictureIds = pictures
					.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
					.Select(x => Convert.ToInt32(x))
					.ToArray();
				foreach (var p in pictureIds)
				{
					model.Pictures.Add(_pictureService.GetPictureUrl(p));
				}
			}
			//categories
			PrepareAllTypesModel(model);

			return View(model);
		}

		[HttpPost]
		public virtual ActionResult Delete(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedView();

			var equipment = _xJInspectionService.GetXJInspectionById(id);
			if (equipment == null)
				//No equipment found with the specified id
				return RedirectToAction("List");

			_xJInspectionService.DeleteXJInspection(equipment);

			//activity log
			_customerActivityService.InsertActivity("DeleteInspection", "删除巡检记录：{0}", equipment.Id);

			SuccessNotification("删除成功");
			return RedirectToAction("List");
		}


		#endregion

		[HttpPost]
		public virtual ActionResult Maintenances(DataSourceRequest command, int planId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedKendoGridJson();

			var categories = _xJMaintenanceService.GetAllMaintenances(
				planId: planId,
				pageIndex: command.Page - 1,
				pageSize: command.PageSize);
			var gridModel = new DataSourceResult
			{
				Data = categories.Select(x =>
				{
					x.StateName = Enum.GetName(typeof(MaintenanceStateEnum), x.State);
					return x;
				}),
				Total = categories.TotalCount
			};
			return Json(gridModel);
		}

		public virtual ActionResult MaintenancesDelete(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageInspections))
				return AccessDeniedView();

			var maintenance = _xJMaintenanceService.GetXJMaintenanceById(id);
			if (null != maintenance && !maintenance.Deleted)
			{
				_xJMaintenanceService.DeleteMaintenance(maintenance);
			}

			return new NullJsonResult();
		}

		[ChildActionOnly]
		public virtual ActionResult Statistics()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return Content("");

			return PartialView();
		}

		[AcceptVerbs(HttpVerbs.Get)]
		public virtual ActionResult LoadStatistics(string period)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return Content("");

			var result = new List<object>();

			var nowDt = _dateTimeHelper.ConvertToUserTime(DateTime.Now);
			var timeZone = _dateTimeHelper.CurrentTimeZone;

			var culture = new CultureInfo(_workContext.WorkingLanguage.LanguageCulture);

			switch (period)
			{
				case "year":
					//year statistics
					var yearAgoDt = nowDt.AddYears(-1).AddMonths(1);
					var searchYearDateUser = new DateTime(yearAgoDt.Year, yearAgoDt.Month, 1);
					if (!timeZone.IsInvalidTime(searchYearDateUser))
					{
						for (int i = 0; i <= 12; i++)
						{
							result.Add(new
							{
								date = searchYearDateUser.Date.ToString("Y", culture),
								value = _xJInspectionService.GetAllInspections(
									startOn: _dateTimeHelper.ConvertToUtcTime(searchYearDateUser, timeZone),
									endOn: _dateTimeHelper.ConvertToUtcTime(searchYearDateUser.AddMonths(1), timeZone),
									pageIndex: 0,
									pageSize: 1).TotalCount.ToString()
							});

							searchYearDateUser = searchYearDateUser.AddMonths(1);
						}
					}
					break;

				case "month":
					//month statistics
					var monthAgoDt = nowDt.AddDays(-30);
					var searchMonthDateUser = new DateTime(monthAgoDt.Year, monthAgoDt.Month, monthAgoDt.Day);
					if (!timeZone.IsInvalidTime(searchMonthDateUser))
					{
						for (int i = 0; i <= 30; i++)
						{
							result.Add(new
							{
								date = searchMonthDateUser.Date.ToString("M", culture),
								value = _xJInspectionService.GetAllInspections(
									startOn: _dateTimeHelper.ConvertToUtcTime(searchMonthDateUser, timeZone),
									endOn: _dateTimeHelper.ConvertToUtcTime(searchMonthDateUser.AddDays(1), timeZone),
									pageIndex: 0,
									pageSize: 1).TotalCount.ToString()
							});

							searchMonthDateUser = searchMonthDateUser.AddDays(1);
						}
					}
					break;

				case "week":
				default:
					//week statistics
					var weekAgoDt = nowDt.AddDays(-7);
					var searchWeekDateUser = new DateTime(weekAgoDt.Year, weekAgoDt.Month, weekAgoDt.Day);
					if (!timeZone.IsInvalidTime(searchWeekDateUser))
					{
						for (int i = 0; i <= 7; i++)
						{
							result.Add(new
							{
								date = searchWeekDateUser.Date.ToString("d dddd", culture),
								value = _xJInspectionService.GetAllInspections(
									startOn: _dateTimeHelper.ConvertToUtcTime(searchWeekDateUser, timeZone),
									endOn: _dateTimeHelper.ConvertToUtcTime(searchWeekDateUser.AddDays(1), timeZone),
									pageIndex: 0,
									pageSize: 1).TotalCount.ToString()
							});

							searchWeekDateUser = searchWeekDateUser.AddDays(1);
						}
					}
					break;
			}

			return Json(result, JsonRequestBehavior.AllowGet);
		}
	}
}